package org.realogic.btp.sequence.service.impl;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

import org.realogic.btp.sequence.entity.Sequence;
import org.realogic.btp.sequence.service.SequenceGenerateService;
import org.realogic.cfm.persistence.jdbc.KJdbcDao;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service("btp.sequenceGenerateService")
public class SequenceGenerateServiceImpl extends KJdbcDao implements SequenceGenerateService {

	// @Transactional(readOnly = false, propagation = Propagation.SUPPORTS)
	public String generateSequence(final String aVariableName) {
		JdbcTemplate jdbcTemplate = this.getJdbcTemplate();
		String s = jdbcTemplate.execute(new ConnectionCallback<String>() {
			public String doInConnection(final Connection conn) throws SQLException, DataAccessException {
				return generateSequence(aVariableName, conn);
			}
		});
		return s;
	}

	public Sequence generateSequence(final String aVariableName, final int size) {
		JdbcTemplate jdbcTemplate = this.getJdbcTemplate();
		Sequence s = jdbcTemplate.execute(new ConnectionCallback<Sequence>() {
			public Sequence doInConnection(final Connection conn) throws SQLException, DataAccessException {
				return generateSequence(aVariableName, size, conn);
			}
		});
		return s;
	}

	private String generateSequence(String aVariableName, Connection aConn) {
		Sequence tmpSequence = generateSequence(aVariableName, 1, aConn);
		return tmpSequence.newSequenceValue();
	}
	
	/**
	 * @param aVariableName 变量名称
	 * @param size 一次性取出多少个流水号，应用于数据批量导入或子表
	 * @param aConn 数据库连接
	 * @return Sequence
	 */
	private Sequence generateSequence(String aVariableName, int size, Connection aConn) {
		boolean flag = true;
		long startValue = -1;
		long endValue = -1;

		long currentTime = System.currentTimeMillis();
		Timestamp currentTimestamp = new Timestamp(currentTime);
		Sequence tmpSequence = new Sequence();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			pstmt = aConn.prepareStatement("SELECT id,value,dateflag,prefix,blocksize,digit,lastmodtime FROM sys_sequencenumber WHERE variablename=?");
			pstmt.setString(1, aVariableName);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				tmpSequence.setVariableName(aVariableName);
				tmpSequence.setId(rs.getLong(1));
				tmpSequence.setValue(rs.getLong(2));
				tmpSequence.setDateflag(rs.getInt(3));
				tmpSequence.setPrefix(rs.getString(4));
				tmpSequence.setBlockSize(rs.getInt(5));
				tmpSequence.setDigit(rs.getInt(6));
				tmpSequence.setLastmodtime(rs.getTimestamp(7));
				if (tmpSequence.getDateflag() > 9) {
					int tmpCurrent = intOfCurrentDate(aVariableName, String.valueOf(tmpSequence.getDateflag()).length(), currentTime);
					if (tmpSequence.getDateflag() == tmpCurrent) {
						startValue = tmpSequence.getValue() + 1;
					} else if (tmpSequence.getDateflag() < tmpCurrent) {
						tmpSequence.setDateflag(tmpCurrent);
						startValue = 1;
					} else if (tmpSequence.getDateflag() > tmpCurrent) {
						// nextValue = tmpSequence.getValue() + 1;
						flag = false;
						throw new IllegalStateException("错误：流水号[" + aVariableName + "]生成失败,规则表记录的时间大于系统当前时间...");
					}
				} else {
					startValue = tmpSequence.getValue() + 1;
				}
			} else {
				flag = false;
				throw new IllegalStateException("错误：流水号[" + aVariableName + "]在规则表中未定义...");
			}
		} catch (SQLException sqlEx) {
			flag = false;
			throw new IllegalStateException("错误：流水号[" + aVariableName + "]生成失败," + sqlEx.getLocalizedMessage() + "...");
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
			} catch (SQLException e) {
			}
			rs = null;
			try {
				if (pstmt != null) {
					pstmt.close();
				}
			} catch (SQLException e) {

			}
			pstmt = null;
		}

		if (flag) {
			// 记录下一个值
			endValue = startValue + size;
			tmpSequence.setStartValue(startValue);
			tmpSequence.setEndValue(endValue);
			// 更新最新的流水号
			pstmt = null;
			try {
				pstmt = aConn.prepareStatement("UPDATE sys_sequencenumber SET value=?,dateflag=?,lastmodtime=? WHERE variablename=? and lastmodtime<?");
				pstmt.setLong(1, endValue);
				pstmt.setInt(2, tmpSequence.getDateflag());
				pstmt.setTimestamp(3, currentTimestamp);
				pstmt.setString(4, aVariableName);
				pstmt.setTimestamp(5, currentTimestamp);
				flag = (pstmt.executeUpdate() == 1);
			} catch (SQLException sqlEx) {
				flag = false;
				throw new IllegalStateException("错误：流水号[" + aVariableName + "]生成失败," + sqlEx.getLocalizedMessage() + "...");
			} finally {
				try {
					if (pstmt != null) {
						pstmt.close();
					}
				} catch (SQLException e) {

				}
				pstmt = null;
			}
		}
		if (flag == false) {
			throw new IllegalStateException("错误:流水号生成失败...");
		}
		return tmpSequence;
	}

	private int intOfCurrentDate(String aVariableName, int theLength, long theTime) {
		Date tmpDate = new Date(theTime);
		String tmp = tmpDate.toString();
		String tmpValue = tmp.substring(2, 4).concat(tmp.substring(5, 7)).concat(tmp.substring(8, 10));
		if (theLength == 6) {
			tmpValue = tmp.substring(2, 4).concat(tmp.substring(5, 7)).concat(tmp.substring(8, 10));
		} else if (theLength == 4) {
			tmpValue = tmp.substring(2, 4).concat(tmp.substring(5, 7));
		} else if (theLength == 2) {
			tmpValue = tmp.substring(2, 4);
		} else {
			throw new IllegalStateException("错误：流水号[" + aVariableName + "]时间格式不符合规范...");
		}
		return Integer.parseInt(tmpValue);
	}

}
